﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CashFlow.Entities.Models;
using CashFlow.Repository;
using CashFlow.Entities;
using CashFlow.AzureRepository;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Web.Routing;

namespace CashFlow.Web.Controllers
{
	[HandleError]
	public class BillController : Controller
	{
		private IBillRepository billRepository;

		#region Constructors
		public BillController()
		{
		}

		public BillController(IBillRepository repository)
		{
			this.billRepository = repository;
			billRepository.TenantId = Environment.GetTenant().Id;
		}

		protected override void Initialize(RequestContext requestContext)
		{
			if (billRepository == null)
			{
				billRepository = new AzureBillRepository(Environment.GetTenant().Id);
			}

			base.Initialize(requestContext);
		}

		#endregion
		
		//
		// GET: /Bills/
		public ActionResult Index()
		{
			//var model = FakeData.BillProvider.GetBillListModel();
			var entities = billRepository.GetAll().ToList();
			var model = entities.Select(e => (BillListModel)e);
			return View(model.
				OrderBy(m => m.Recurrence).
				ThenBy(m => m.Details).
				ThenBy(m => m.Amount));
		}

		//
		// GET: /Bill/Create
		public ActionResult Add()
		{
			var model = BillModel.GetDefaultModel(Environment.GetTenant());
			return View(model);
		}

		//
		// POST: /Bill/Create

		[HttpPost]
		public ActionResult Add(BillModel	model)
		{
			//TODO: vvs p2 add logging (tracing & errors logging).
			Action<Bill> saveAction = (bill) => { billRepository.Create(bill); };
			var result = Save(model, saveAction, "Index");
			return result;
		}

		private ActionResult Save(BillModel model, Action<Bill> saveAction, string redirectActionName)
		{
			ActionResult result = RedirectToAction(redirectActionName);
			if (ModelState.IsValid)
			{
				Task.Factory.StartNew(() => SaveToRepository(model, saveAction));
			} 
			else 
			{
				ModelState.AddModelError("", Properties.Resources.ErrorInvalidModel);
				result = View(model);
			}
			return result;
		}

		private void SaveToRepository(BillModel model, Action<Bill> saveAction)
		{
			Bill bill = null;
			try
			{
				model.TenantId = Environment.GetTenant().Id;
				bill = (Bill)model;
				saveAction(bill);
			}
			catch (Exception exc)
			{
				Trace.TraceError(
					"ERROR: {0} | {1} | {2} | {3} | {4} ", 
					this.GetType().FullName, 
					System.Reflection.MethodBase.GetCurrentMethod().Name, 
					"Exception", 
					exc,
					bill);
				//TODO: vvs p2 log & submit error to error handler.
				//ModelState.AddModelError("", Properties.Resources.ErrorModelSave);
			}
		}

		//
		// GET: /Bill/Edit/5
		public ActionResult Edit(string id)
		{
			ActionResult result = null;
			var entity = billRepository.GetById(id);
			if (entity == null)
			{
				//TODO: vvs p2 create error event for error indicator.
				Trace.TraceError("WARNING: {0}, {1}, {2}, {3}, {4}",
					this.GetType().FullName,
					System.Reflection.MethodBase.GetCurrentMethod().Name,
					"Bill not found. Tenant/Id: ",
					Environment.GetTenant().Id,
					id);
				result = RedirectToAction("Index");
			}
			else
			{
				var model = (BillModel)entity;
				result = View(model);
			}
			return result;
		}

		//
		// POST: /Bill/Edit/5

		[HttpPost]
		public ActionResult Edit(BillModel model)
		{
			//TODO: vvs p2 add logging (tracing & errors logging).
			Action<Bill> saveAction = (bill) => { billRepository.Update(bill); };
			var result = Save(model, saveAction, "Index");
			return result;
		}

		//
		// POST: /Bill/Delete/5
		[HttpPost]
		public void Delete(string id)
		{
			Task.Factory.StartNew(() => billRepository.Delete(id));
		}

		[HttpPost]
		public void UnDelete(string id)
		{
			Task.Factory.StartNew(() => billRepository.UnDelete(id));
		}
	}
}
